"""
【物动分离】
Definition: 建造者模式（Builder Pattern），将一个复杂对象的构建过程分离成多个简单的步骤，
Scene: 灵活地组合和构建不同的对象。

Characters:
    产品类（Product）：产品类定义了具体的产品对象，并且包含了组成该产品的各个部件。
    抽象建造者类（Builder）：抽象建造者类定义了创建产品各个部件的抽象方法，以及返回最终产品的方法。
    具体建造者类（ConcreteBuilder）：具体建造者类实现了抽象建造者类中定义的方法，负责创建具体的产品。
    指挥者类（Director）：指挥者类负责调用具体建造者类中的方法来完成产品的构建，它通常并不直接创建产品，而是通过 Builder 来间接创建产品。

Director -> ConcreteBuilderA —> Product —> Builder
         -> ConcreteBuilderB -> Product -> Builder

Code: Product 是产品类，包含了需要构建的各个部件。Builder 是抽象建造者类，定义了创建产品各个部件的抽象方法，以及返回最终产品的方法。
      ConcreteBuilder1 和 ConcreteBuilder2 是具体建造者类，分别实现了 Builder 中定义的方法来创建不同类型的产品。
      Director 是指挥者类，负责调用具体建造者类中的方法来完成产品的构建。

客户端代码中，创建一个ConcreteBuilder1的实例，传入指挥者类中。然后调用指挥者类的construct()构建产品。最后，从建造器对象中获取最终构建好的产品并输出。


优点：
    分离对象构建过程。使之变得清晰而灵活。
    可控制对象构建顺序，减少代码重复和耦合度。
缺点：
    增加系统的复杂度和代码量。需要实现多个具体建造者类以及一个指挥者类

"""


class Product:
    def __init__(self):
        self.part_a = None
        self.part_b = None


class Builder:
    def build_part_a(self):
        pass

    def build_part_b(self):
        pass

    def get_result(self):
        pass


class ConcreteBuilder1(Builder):
    def __init__(self):
        self.product = Product()

    def build_part_a(self):
        self.product.part_a = "Part A1"

    def build_part_b(self):
        self.product.part_b = "Part B1"

    def get_result(self):
        return self.product


class ConcreteBuilder2(Builder):
    def __init__(self):
        self.product = Product()

    def build_part_a(self):
        self.product.part_a = "Part A2"

    def build_part_b(self):
        self.product.part_b = "Part B2"

    def get_result(self):
        return self.product


class Director:
    def __init__(self, builder):
        self.builder = builder

    def construct(self):
        self.builder.build_part_a()
        self.builder.build_part_b()

        return self.builder.get_result()


builder_1 = ConcreteBuilder1()
director_1 = Director(builder_1)
product_1 = director_1.construct()
print(f"Pro1: {product_1.part_a}, {product_1.part_b}")
# 输出：Pro1: Part A1, Part B1

builder_2 = ConcreteBuilder2()
director_2 = Director(builder_2)
product_2 = director_2.construct()
print(f"Pro2: {product_2.part_a}, {product_2.part_b}")
# 输出：Pro2: Part A2, Part B2
